Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

core/service/src/androidMain/kotlin/org/meshtastic/core/service/ServiceClient.kt renovate/net.java.dev.jna-jna-5.x (5a8f4966) Text, 5.08 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.service

Tff7b72import T7ee787android.content.ComponentName
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.content.ServiceConnection
Tff7b72import T7ee787android.os.IBinder
Tff7b72import T7ee787android.os.IInterface
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787org.meshtastic.core.common.util.exceptionReporter
Tff7b72import T7ee787java.io.Closeable
Tff7b72import T7ee787java.util.concurrent.locks.ReentrantLock
Tff7b72import T7ee787kotlin.concurrent.withLock

Tff7b72class T56d364BindFailedException Tb4b4b4: Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffbindService failedTa5d6ff"Tb4b4b4)

T8b949e/**
* A generic helper for binding to an Android Service via AIDL. Handles connection lifecycle, thread safety for initial
* binding, and automatic retry for common race conditions.
*
* @param T The type of the AIDL interface.
* @param stubFactory A factory function to convert an [IBinder] to the interface type.
*/
Tff7b72open Tff7b72class T56d364ServiceClientTff7b72<Te6edf3T Tb4b4b4: Te6edf3IInterfaceTff7b72>Tb4b4b4(Tff7b72private Tff7b72val Te6edf3stubFactoryTb4b4b4: Tb4b4b4(Te6edf3IBinderTb4b4b4) Tff7b72-Tff7b72> Te6edf3TTb4b4b4) Tb4b4b4: Te6edf3Closeable Tb4b4b4{

Tff7b72private Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3BIND_RETRY_DELAY_MS Tff7b72= T79c0ff5T79c0ff0T79c0ff0L
Tb4b4b4}

T8b949e/** The currently bound service instance, or null if not connected. */
Tff7b72var Te6edf3servicePTb4b4b4: Te6edf3T? Tff7b72= Tff7b72null

T8b949e/**
* Returns the bound service instance. If not currently connected, this will block the current thread until the
* connection is established.
*
* @throws IllegalStateException If [connect] has not been called.
* @throws IllegalStateException If the service is not bound after waiting.
*/
Tff7b72val Te6edf3serviceTb4b4b4: Te6edf3T
Tff7b72getTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3waitConnectTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3checkNotNullTb4b4b4(Te6edf3servicePTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffService not boundTa5d6ff" Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72var Te6edf3contextTb4b4b4: Te6edf3Context? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3isClosed Tff7b72= Tff7b72true

Tff7b72private Tff7b72val Te6edf3lock Tff7b72= Te6edf3ReentrantLockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3condition Tff7b72= Te6edf3lockTb4b4b4.Te6edf3newConditionTb4b4b4(Tb4b4b4)

T8b949e/**
* Blocks the current thread until the service is connected.
*
* @throws IllegalStateException If [connect] has not been called.
*/
Tff7b72fun Td2a8ffwaitConnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3lockTb4b4b4.Te6edf3withLock Tb4b4b4{
Te6edf3checkTb4b4b4(Te6edf3context Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffConnect must be called before waitConnectTa5d6ff" Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3serviceP Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3conditionTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e/**
* Initiates a binding to the service.
*
* @param c The context to use for binding.
* @param intent The intent used to identify the service.
* @param flags Binding flags (e.g., [Context.BIND_AUTO_CREATE]).
* @throws BindFailedException If the initial bind call fails twice.
*/
Tff7b72suspend Tff7b72fun Td2a8ffconnectTb4b4b4(Te6edf3cTb4b4b4: Te6edf3ContextTb4b4b4, Te6edf3intentTb4b4b4: Te6edf3IntentTb4b4b4, Te6edf3flagsTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3context Tff7b72= Te6edf3c
Tff7b72if Tb4b4b4(Te6edf3isClosedTb4b4b4) Tb4b4b4{
Te6edf3isClosed Tff7b72= Tff7b72false
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3cTb4b4b4.Te6edf3bindServiceTb4b4b4(Te6edf3intentTb4b4b4, Te6edf3connectionTb4b4b4, Te6edf3flagsTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// Handle potential race condition on quick re-bind
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffInitial bind failed, retrying after delay...Ta5d6ff" Tb4b4b4}
Te6edf3delayTb4b4b4(Te6edf3BIND_RETRY_DELAY_MSTb4b4b4)
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3cTb4b4b4.Te6edf3bindServiceTb4b4b4(Te6edf3intentTb4b4b4, Te6edf3connectionTb4b4b4, Te6edf3flagsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3BindFailedExceptionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffIgnoring rebind attempt for already active service connectionTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffcloseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3isClosed Tff7b72= Tff7b72true
Tff7b72try Tb4b4b4{
Te6edf3contextTff7b72?.Te6edf3unbindServiceTb4b4b4(Te6edf3connectionTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3IllegalArgumentExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffIgnoring error during unbind: service might have already been cleaned upTa5d6ff" Tb4b4b4}
Tb4b4b4}
Te6edf3serviceP Tff7b72= Tff7b72null
Te6edf3context Tff7b72= Tff7b72null
Tb4b4b4}

T8b949e/** Called on the main thread when the service is connected. */
Tff7b72open Tff7b72fun Td2a8ffonConnectedTb4b4b4(Te6edf3serviceTb4b4b4: Te6edf3TTb4b4b4) Tb4b4b4{Tb4b4b4}

T8b949e/** Called on the main thread when the service connection is lost. */
Tff7b72open Tff7b72fun Td2a8ffonDisconnectedTb4b4b4(Tb4b4b4) Tb4b4b4{Tb4b4b4}

Tff7b72private Tff7b72val Te6edf3connection Tff7b72=
Tff7b72object Tb4b4b4: T56d364ServiceConnection Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffonServiceConnectedTb4b4b4(Te6edf3nameTb4b4b4: Te6edf3ComponentNameTb4b4b4, Te6edf3binderTb4b4b4: Te6edf3IBinderTb4b4b4) Tff7b72= Te6edf3exceptionReporter Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isClosedTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3s Tff7b72= Te6edf3stubFactoryTb4b4b4(Te6edf3binderTb4b4b4)
Te6edf3serviceP Tff7b72= Te6edf3s
Te6edf3onConnectedTb4b4b4(Te6edf3sTb4b4b4)

Te6edf3lockTb4b4b4.Te6edf3withLock Tb4b4b4{ Te6edf3conditionTb4b4b4.Te6edf3signalAllTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3w Tb4b4b4{ Ta5d6ff"Ta5d6ffService connected after close was called; ignoring stale connectionTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffonServiceDisconnectedTb4b4b4(Te6edf3nameTb4b4b4: Te6edf3ComponentName?Tb4b4b4) Tff7b72= Te6edf3exceptionReporter Tb4b4b4{
Te6edf3serviceP Tff7b72= Tff7b72null
Te6edf3onDisconnectedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.05s